import { reactive } from 'vue'
import { getArrayKey } from './common'
import { isArray } from 'lodash-es'
import { dayjs } from 'element-plus'
export default class aaTable {
    public table: AaTable = reactive({
        ref: undefined,
        pk: 'id',
        data: [],
        loading: false,
        selection: [],
        column: [],
        pagination: true,
        total: 0,
        filter: {
            limit: 10,
            page: 1,
        },
        dragSortLimitField: 'pid',
        acceptQuery: true,
        showComSearch: false,
        dblClickNotEditColumn: [undefined],
        expandAll: false,
        extend: {},
    })

    public before: AaTableBefore
    public after: AaTableAfter

    // 通用搜索数据
    private comSearch: ComSearch = reactive({
        form: {},
        fieldData: new Map(),
    })

    constructor(table: AaTable, before: AaTableBefore = {}, after: AaTableAfter = {}) {
        table.column = table.column.map((item) => {
            return Object.assign({ operator: 'eq' }, item)
        })
        this.table = Object.assign(this.table, table)
        this.before = before
        this.after = after
    }

    /**
     * 通用搜索初始化
     */
    public initComSearch = () => {
        const form: anyObj = {}
        const field = this.table.column

        if (field.length <= 0) return

        for (const key in field) {
            // 关闭搜索的字段
            if (field[key].operator === false) continue

            // 通用搜索表单字段初始化
            const prop = field[key].prop
            if (prop) {
                if (field[key].operator == 'RANGE') {
                    // 范围查询
                    form[prop] = ''
                    form[prop + '-start'] = ''
                    form[prop + '-end'] = ''
                } else if (field[key].operator == 'NULL') {
                    // 复选框
                    form[prop] = false
                } else {
                    // 普通文本框
                    form[prop] = ''
                }

                // 初始化字段的通用搜索数据
                this.comSearch.fieldData.set(prop, {
                    operator: field[key].operator,
                    render: field[key].render,
                    comSearchRender: field[key].comSearchRender,
                })
            }
        }

        this.comSearch.form = Object.assign(this.comSearch.form, form)
    }

    /**
     * 运行前置函数
     * @param funName 函数名
     * @param args 参数
     */
    private runBefore(funName: TableActionEvent | TableHeaderActionEvent, args: any = {}): boolean {
        if (this.before && this.before[funName] && typeof this.before[funName] == 'function') {
            return this.before[funName]!({ ...args }) === false ? false : true
        }
        return true
    }
    /**
     * 运行后置函数
     * @param funName 函数名
     * @param args 参数
     */
    private runAfter(funName: TableActionEvent | TableHeaderActionEvent, args: any = {}): boolean {
        if (this.after && this.after[funName] && typeof this.after[funName] == 'function') {
            return this.after[funName]!({ ...args }) === false ? false : true
        }
        return true
    }

    public onTableHeaderAction(event: TableHeaderActionEvent, data: anyObj) {
        if (this.runBefore(event, data) === false) return
        const actionFun = new Map([
            // 刷新表格数据
            [
                'refresh',
                () => {
                    this.table.data = []
                    this.getData()
                },
            ],
            // 添加数据
            ['add', () => {}],
            // 编辑数据
            ['edit', () => {}],
            // 删除数据
            ['delete', () => {}],
            [
                'unfold',
                () => {
                    if (!this.table.ref) {
                        console.warn('Collapse/expand failed because table ref is not defined')
                        return
                    }
                    this.table.expandAll = data.unfold
                    this.table.ref.unFoldAll(data.unfold)
                },
            ],
            // 快速查询数据
            [
                'quickSearch',
                () => {
                    this.onTableHeaderAction('refresh', { keyword: this.table.filter?.quickSearch })
                },
            ],
            // 修改列显示状态
            [
                'columnDisplay',
                () => {
                    const columnKey = getArrayKey(this.table.column, 'prop', data.field)
                    this.table.column[columnKey].show = data.value
                },
            ],
        ])
        const action = actionFun.get(event)
        action!.call(this)
        return this.runAfter(event, data)
    }

    /**
     * 表格内的事件统一响应
     * @param event 事件:selection-change=选中项改变,page-size-change=每页数量改变,current-page-change=翻页,sort-change=排序,edit=编辑,delete=删除,field-change=单元格值改变,com-search=公共搜索
     * @param data 携带数据
     */
    public onTableAction(event: TableActionEvent, data: anyObj) {
        if (this.runAfter(event, data) === false) return
        const actionFun = new Map([
            [
                'selection-change',
                () => {
                    this.table.selection = data as TableRow[]
                },
            ],
            [
                'page-size-change',
                () => {
                    this.table.filter!.limit = data.pageSize
                    this.onTableHeaderAction('refresh', { event: 'page-size-change', ...data })
                },
            ],
            [
                'current-page-change',
                () => {
                    this.table.filter!.page = data.curPage
                    this.onTableHeaderAction('refresh', { event: 'current-page-change', ...data })
                },
            ],
            [
                'com-search',
                () => {
                    this.table.filter!.search = this.getComSearchData()

                    // 刷新表格
                    this.onTableHeaderAction('refresh', { event: 'com-search', data: this.table.filter!.search })
                },
            ],
        ])
        const action = actionFun.get(event)
        action!.call(this)
        return this.runAfter(event, data)
    }

    /**
     * 设置通用搜索数据
     */
    private setComSearchData = (query: anyObj) => {
        for (const key in this.table.column) {
            const prop = this.table.column[key].prop
            if (prop && typeof query[prop] !== 'undefined') {
                const queryProp = query[prop] ?? ''
                if (this.table.column[key].operator == 'RANGE') {
                    const range = queryProp.split(',')
                    if (this.table.column[key].render == 'datetime' || this.table.column[key].comSearchRender == 'date') {
                        if (range && range.length >= 2) {
                            const rangeDayJs = [dayjs(range[0]), dayjs(range[1])]
                            if (rangeDayJs[0].isValid() && rangeDayJs[1].isValid()) {
                                if (this.table.column[key].comSearchRender == 'date') {
                                    this.comSearch.form[prop] = [rangeDayJs[0].format('YYYY-MM-DD'), rangeDayJs[1].format('YYYY-MM-DD')]
                                } else {
                                    this.comSearch.form[prop] = [
                                        rangeDayJs[0].format('YYYY-MM-DD HH:mm:ss'),
                                        rangeDayJs[1].format('YYYY-MM-DD HH:mm:ss'),
                                    ]
                                }
                            }
                        }
                    } else {
                        this.comSearch.form[prop + '-start'] = range[0] ?? ''
                        this.comSearch.form[prop + '-end'] = range[1] ?? ''
                    }
                } else if (this.table.column[key].operator == 'NULL') {
                    this.comSearch.form[prop] = queryProp ? true : false
                } else if (this.table.column[key].render == 'datetime' || this.table.column[key].comSearchRender == 'date') {
                    const propDayJs = dayjs(queryProp)
                    if (propDayJs.isValid()) {
                        this.comSearch.form[prop] = propDayJs.format(
                            this.table.column[key].comSearchRender == 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'
                        )
                    }
                } else {
                    this.comSearch.form[prop] = queryProp
                }
            }
        }
    }

    /**
     * 获取通用搜索数据
     */
    private getComSearchData = () => {
        const comSearchData: comSearchData[] = []

        for (const key in this.comSearch.form) {
            if (!this.comSearch.fieldData.has(key)) continue

            let val = null
            const fieldDataTemp = this.comSearch.fieldData.get(key)
            if (fieldDataTemp.render == 'datetime' && fieldDataTemp.operator == 'RANGE') {
                // 时间范围
                if (this.comSearch.form[key] && this.comSearch.form[key].length >= 2) {
                    if (fieldDataTemp.comSearchRender == 'date') {
                        val = this.comSearch.form[key][0] + ' 00:00:00' + ',' + this.comSearch.form[key][1] + ' 23:59:59'
                    } else {
                        val = this.comSearch.form[key][0] + ',' + this.comSearch.form[key][1]
                    }
                }
            } else if (fieldDataTemp.operator == 'RANGE') {
                // 普通的范围筛选，公共搜索初始化时已准备好 start 和 end 字段
                if (!this.comSearch.form[key + '-start'] && !this.comSearch.form[key + '-end']) {
                    continue
                }
                val = this.comSearch.form[key + '-start'] + ',' + this.comSearch.form[key + '-end']
            } else if (this.comSearch.form[key]) {
                val = this.comSearch.form[key]
            }

            if (val === null) continue
            if (isArray(val) && !val.length) continue

            comSearchData.push({
                field: key,
                val: val,
                operator: fieldDataTemp.operator,
                render: fieldDataTemp.render,
            })
        }

        return comSearchData
    }

    //  网络请求相关
    getData() {
        console.log(this.table.filter)
    }
}
